/*-------------------------------------------------------------------------
 *
 * llvmjit_types.c
 *	  JIT发出代码所需的类型列表。
 *
 * JIT发出代码通常需要访问结构元素、创建具有正确签名的函数等。为了使这些类型能够以较低的可能性保持同步，并防止定义不同步，此文件列出了需要直接从LLVM访问的类型和函数。
 *
 * 当后端第一次使用LLVM时，将加载此文件的位代码版本。所需的类型和签名将存储在Struct*、Type*、Func*变量中。
 *
 * 注意：此文件不会链接到服务器，它只是转换为位代码。
 *
 *
 * Copyright (c) 2016-2022, PostgreSQL Global Development Group
 *
 * IDENTIFICATION
 *	  src/backend/jit/llvm/llvmjit_types.c
 *
 *-------------------------------------------------------------------------
 */

#include "postgres.h"

#include "access/htup.h"
#include "access/htup_details.h"
#include "access/tupdesc.h"
#include "catalog/pg_attribute.h"
#include "executor/execExpr.h"
#include "executor/nodeAgg.h"
#include "executor/tuptable.h"
#include "fmgr.h"
#include "nodes/execnodes.h"
#include "nodes/memnodes.h"
#include "utils/expandeddatum.h"
#include "utils/palloc.h"


/*
 * JIT 所需类型的列表。这些必须是非静态的，否则
 * clang/LLVM 会省略它们。由于此文件永远不会链接到
 * 任何东西，这并无害。
 */
PGFunction	TypePGFunction;
size_t		TypeSizeT;
bool		TypeStorageBool;

ExecEvalSubroutine TypeExecEvalSubroutine;
ExecEvalBoolSubroutine TypeExecEvalBoolSubroutine;

NullableDatum StructNullableDatum;
AggState	StructAggState;
AggStatePerGroupData StructAggStatePerGroupData;
AggStatePerTransData StructAggStatePerTransData;
ExprContext StructExprContext;
ExprEvalStep StructExprEvalStep;
ExprState	StructExprState;
FunctionCallInfoBaseData StructFunctionCallInfoData;
HeapTupleData StructHeapTupleData;
HeapTupleHeaderData StructHeapTupleHeaderData;
MemoryContextData StructMemoryContextData;
TupleTableSlot StructTupleTableSlot;
HeapTupleTableSlot StructHeapTupleTableSlot;
MinimalTupleTableSlot StructMinimalTupleTableSlot;
TupleDescData StructTupleDescData;
PlanState	StructPlanState;
MinimalTupleData StructMinimalTupleData;


/*
 * 为了确定函数在内联时需要具有哪些属性（例如取决于
 * 编译器版本和设置），我们简单地复制此函数的属性。
 */
extern Datum AttributeTemplate(PG_FUNCTION_ARGS);
Datum AttributeTemplate(PG_FUNCTION_ARGS)
{
	AssertVariableIsOfType(&AttributeTemplate, PGFunction);

	PG_RETURN_NULL();
}

/*
 * 还有一些“模板”，为我们提供与函数指针类型相对应的函数类型示例。
 */

extern void ExecEvalSubroutineTemplate(ExprState *fc_state,
									   struct ExprEvalStep *fc_op,
									   ExprContext *fc_econtext);
void ExecEvalSubroutineTemplate(ExprState *fc_state,
						   struct ExprEvalStep *fc_op,
						   ExprContext *fc_econtext)
{
	AssertVariableIsOfType(&ExecEvalSubroutineTemplate,
						   ExecEvalSubroutine);
}

extern bool ExecEvalBoolSubroutineTemplate(ExprState *fc_state,
										   struct ExprEvalStep *fc_op,
										   ExprContext *fc_econtext);
bool ExecEvalBoolSubroutineTemplate(ExprState *fc_state,
							   struct ExprEvalStep *fc_op,
							   ExprContext *fc_econtext)
{
	AssertVariableIsOfType(&ExecEvalBoolSubroutineTemplate,
						   ExecEvalBoolSubroutine);

	return false;
}

/*
 * Clang 以不同于存储值的方式（作为 i1）表示由函数返回的
 * stdbool.h 风格的布尔值。因此，我们不仅需要
 * TypeBool（上述），还需要确定返回的
 * 整数宽度的方法。这样可以让我们与不使用 stdbool 的
 * 架构保持兼容。
 */
extern bool FunctionReturningBool(void);
bool FunctionReturningBool(void)
{
	return false;
}

/*
 * 为了强制 JIT 使用的函数的签名存在，
 * 引用所需的函数。这同样必须是非静态的，以避免
 * 被视为不必要而被移除。
 */
void	   *referenced_functions[] =
{
	ExecAggInitGroup,
	ExecAggTransReparent,
	ExecEvalAggOrderedTransDatum,
	ExecEvalAggOrderedTransTuple,
	ExecEvalArrayCoerce,
	ExecEvalArrayExpr,
	ExecEvalConstraintCheck,
	ExecEvalConstraintNotNull,
	ExecEvalConvertRowtype,
	ExecEvalCurrentOfExpr,
	ExecEvalFieldSelect,
	ExecEvalFieldStoreDeForm,
	ExecEvalFieldStoreForm,
	ExecEvalFuncExprFusage,
	ExecEvalFuncExprStrictFusage,
	ExecEvalGroupingFunc,
	ExecEvalMinMax,
	ExecEvalNextValueExpr,
	ExecEvalParamExec,
	ExecEvalParamExtern,
	ExecEvalRow,
	ExecEvalRowNotNull,
	ExecEvalRowNull,
	ExecEvalSQLValueFunction,
	ExecEvalScalarArrayOp,
	ExecEvalHashedScalarArrayOp,
	ExecEvalSubPlan,
	ExecEvalSysVar,
	ExecEvalWholeRowVar,
	ExecEvalXmlExpr,
	MakeExpandedObjectReadOnlyInternal,
	slot_getmissingattrs,
	slot_getsomeattrs_int,
	strlen,
	varsize_any,
	ExecInterpExprStillValid,
};
